<template>
    <section id="ansible-manager">
        <el-card class="bg-card">
    <el-row class="hosts-select"  :gutter="10">
        <el-col :span="3" :offset="1">
        <el-select v-model="hostItems.selected" filterable placeholder="请选择主机集群" @change="changeItem" @focus="chooseHosts" size="small">
            <el-option
                    v-for="item in hostItems.options"
                    :label="item.name"
                    :value="item.name">
            </el-option>
        </el-select>
        </el-col>
        <el-col :span="1">
            <el-popover
                    title="服务器清单"
                    placement="bottom"
                    width="300"
                    trigger="click">
                <ol class="ip-show">
                    <li v-for="ip in this.presentIpList">{{ip}}</li>
                </ol>
                <el-button slot="reference" :disabled="buttonClick" size="small">明细</el-button>
            </el-popover>
        </el-col>

        <el-col :span="1">
            <el-popover
                    v-model="visible2"
                    title="服务器清单编辑"
                    placement="bottom"
                    width="530"
                    trigger="click">
                <el-transfer v-model="ipLists" :data="ipAllLists" :titles="['所有服务器', '当前服务器']"
                             :button-texts="['删除', '增加']"
                ></el-transfer>
                <div style="text-align: right; margin-top:10px;margin-bottom:5px;margin-right: 10px">
                    <el-button type="success" size="small" @click=cancelEdit>取消</el-button>
                    <el-button type="danger" size="small" @click=confirmEdit>确定</el-button>
                </div>
                <el-button slot="reference" type="primary" :disabled="buttonClick" @click="getIpArray" size="small">编辑</el-button>
            </el-popover>
        </el-col>

        <el-col :span="1">
            <el-popover
                    v-model="visible3"
                    title="新增主机组"
                    placement="bottom"
                    width="530"
                    trigger="click">
                <el-input

                        class="add-group-input"
                        placeholder="请输入集群组名"
                        v-model="newIpGroupItem.name"
                        clearable
                        size="mini"
                        style="width: 200px;margin-bottom: 5px"
                >
                </el-input>
                <el-transfer v-model="ipLists" :data="ipAllLists" :titles="['所有服务器', newIpGroupItem.name ? newIpGroupItem.name : 'new group']"

                ></el-transfer>
                <div style="text-align: right; margin-top:10px;margin-bottom:5px;margin-right: 10px">
                    <el-button type="success" size="mini" @click="cancelEdit2" >取消</el-button>
                    <el-button type="danger" size="mini" @click="confirmAdd">添加</el-button>
                </div>
                <el-button slot="reference" type="warning" @click="newIpGroup" size="small">新增</el-button>
            </el-popover>
        </el-col>
    </el-row>
    <el-row style="margin-top: 10px;margin-bottom: 5px" :gutter="50">
        <el-col :span="11" :offset="1">
            <el-radio v-model="ansibleMethod" label="module"  size="mini">模块管理</el-radio>
            <el-radio v-model="ansibleMethod" label="playbook"  size="mini" @change="buttonClickExec = true">剧本管理</el-radio>
        </el-col>

    </el-row>

    <el-row  :gutter="50" v-if="ansibleMethod === 'module'">

            <el-col :span="11" :offset="1" >

                <el-form ref="moduleform" :model="moduleform" label-width="100px" style=" border:1px solid #ccc ; margin: 1px;background-color: #fdf6e3;border-radius: 5px" size="mini">
                    <el-form-item label="模块类型" style="margin-top: 22px"
                                  prop="name"
                                  :rules="[{ required: true, message: '请输入活动名称', trigger: 'blur' }]"
                    >
                        <el-select v-model="moduleform.name" placeholder="请选择模块" style="width: 500px;" @change="changeUsage">
                            <el-option label="ping" value="ping"></el-option>
                            <el-option label="shell" value="shell"></el-option>
                            <el-option label="copy" value="copy"></el-option>
                            <el-option label="yum" value="yum"></el-option>
                            <el-option label="cron" value="cron"></el-option>
                            <el-option label="file" value="file"></el-option>
                            <el-option label="script" value="script"></el-option>
                            <el-option label="user" value="user"></el-option>

                        </el-select>
                    </el-form-item>
                    <el-form-item label="模块参数"
                                  prop="describe"
                                  :rules="[{ required: true, message: '请输入活动名称', trigger: 'blur' }]"
                    >
                        <el-input v-model="moduleform.describe" style="width: 500px" :placeholder="moduleform.ansibleUsage"></el-input>
                    </el-form-item>
                    <el-form-item label="预览">
                        <el-input v-model="moduleform.commandLine" style="width: 500px" :placeholder="moduleform.ansibleUsage" readonly ></el-input>
                    </el-form-item>

                    <el-form-item>
                        <el-button size="mini" type="primary" @click="runAnsibleCmdByModule('moduleform')"><i class="iconfont" style="font-size: 10px" >&#xe61b;</i>  执行</el-button>
                        <el-button size="mini">撤销</el-button>

                    </el-form-item>

                </el-form>

            </el-col>
            <el-col :span="11">

                <div
                        v-loading="ansibleModuleOutPutLoading"
                        element-loading-text="正在执行中"
                        element-loading-spinner="el-icon-loading"
                        element-loading-background="rgba(0, 0, 0, 0.8)"
                >
                <el-input
                        type="textarea"
                        :autosize="{ minRows: 9.5, maxRows: 30}"
                        placeholder="ansible执行结果"
                        v-model="ansibleModuleResult"
                        readonly

                >

                </el-input>
                </div>
            </el-col>

        </el-row>


    <el-row  :gutter="50" v-else>
        <el-col :span="11" :offset="1">
            <div class="title-toor" >
                <el-select v-model="playbookValue" placeholder="请选择" @change="loadYaml" size="mini">
                    <el-option-group
                            v-for="group in playbookOptions"
                            :key="group.label"
                            :label="group.label">
                        <el-option
                                v-for="item in group.options"
                                :label="item.label ? item.label : item.name"
                                :value="item.value ? item.value : item.path"
                                :disabled="item.disabled">
                        </el-option>
                    </el-option-group>
                </el-select>

                <el-upload
                        v-if="playbookValue ==='upload-yaml'"
                        style="display: inline"
                        class="upload-demo"
                        action="http://127.0.0.1:8088/upload"
                        accept=".yaml"
                        :show-file-list="false"
                        :before-upload="beforeAvatarUpload"
                        :on-success="handleAvatarSuccess"
                        :on-error="handleAvatarError"
                        :file-list="fileList">
                    <el-button size="mini" type="primary" >点击上传</el-button>
                    <div slot="tip" class="el-upload__tip" style="display: inline">  只能上传yaml文件，且不超过500kb</div>

                </el-upload>


            </div>
            <edit-yaml ></edit-yaml>

        </el-col>


        <el-col :span="11">
            <div class="title-toor" id="testjquery"><i class="iconfont" style="font-size: 20px;color: black">&#xe761;</i></div>
            <div
                    v-loading="ansiblePlaybookOutPutLoading"
                    element-loading-text="正在执行中"
                    element-loading-spinner="el-icon-loading"
                    element-loading-background="rgba(0, 0, 0, 0.8)"
            >

                <el-input
                        type="textarea"
                        :rows="28.5"
                        placeholder="ansible-playbook"
                        v-model="yamlSyntaxErrorMsgOrExecOutput"
                        style="margin-top: 3px"
                        readonly

                >
                </el-input>
                </div>
        </el-col>
        <el-col :span="24" :offset="1">
            <el-button-group style="display: inline">
                <el-button type="primary"  size="mini"  @click="yamlSyntaxCheck" > <i class="fa fa-question-circle-o" style="font-size:15px;"></i>  yaml 语法检测</el-button>
                <el-button type="warning"   size="mini" :disabled="buttonClickExec" @click="doAnsibleJob" style="margin-left: 5px">执行  <i class="iconfont" style="font-size: 10px">&#xe61b;</i></el-button>
            </el-button-group>

        </el-col>


    </el-row>

        </el-card>




    </section>
</template>

<script>
    import { getHostList,getIpLists,updateItemHosts,AddItemHosts,LoadTemplateFile,getTemplateLists,runAnsibleModuleCmd,runAnsiblePlaybook } from '../../api/api'
    //http://www.cnblogs.com/wenruo/p/8274958.html
    import CodeMirror from 'codemirror'
    //import 'codemirror/lib/codemirror.css'
    //import 'codemirror/theme/rubyblue.css'
    //require ('script-loader!jsonlint')
   // import 'codemirror/mode/javascript/javascript'
    import editYaml from '../../components/edit/edit.vue'
    import $ from 'jquery' //引入jquery 检测输入yaml内容是否格式错误
    import jsyaml from  '../../assets/js/js-yaml.min'

    export default {
        name: 'jsonEditor',
        data() {
            return {
                jsonEditor: false,
                input: "test input",
                ansibleMethod: "module",
                moduleform: {   //模块
                    name: '',
                    describe: '',
                    ansibleUsage: 'copy this to that',
                    commandLine: "",

                },
                ansibleModuleResult: "",
                ansibleModuleOutPutLoading:false,
                presentIpList: [],
                visible2: false, //服务器清单编辑
                ipAll: [],
                ipAllLists: [],
                ipLists: [],  //索引数组
                hostItems: {
                    options: [],
                    selected: "",
                },

                visible3: false, //新增服务集群分组
                newIpGroupItem: {
                    name: "",
                    newIpList: ""
                },

                buttonClick: true,
                buttonClickExec: true,
                  //语法检测和输出结果
                ansiblePlaybookOutPutLoading:false,
                yamlSyntaxErrorMsgOrExecOutput: " ",

                playbookOptions: [
                    {
                    label: '模板',
                    options: [{
                        value: '/template/yaml/ansible/user.yaml',
                        name: 'create-user'
                    }, {
                        value: '/template/yaml/ansible/file.yaml',
                        label: 'file-create'
                    }]
                }, {
                    label: '上传',
                    options: [{
                        value: 'sql',
                        label: '*.sql',
                        disabled: true
                    }, {
                        value: 'upload-yaml',
                        label: '*.yaml'
                    }, {
                        value: 'sh',
                        label: '*.sh',
                        disabled: true
                    }, {
                        value: 'json',
                        label: '*.json',
                        disabled: true
                    }]
                },
                    {
                        label: '输入',
                        options: [{
                            value: 'Yaml',
                            label: 'yaml'
                        }]
                    }],
                playbookValue: '',
                //上传文件
                fileList: [],


            }
        },
        props: {
            value: String,
            changeFn: Function
        },
        watch: {
            value(value) {
                const editor_value = this.jsonEditor.getValue()
                if (value !== editor_value) {
                    this.jsonEditor.setValue(JSON.stringify(JSON.parse(this.value), null, 2))
                }
            }
        },
        /*
        mounted() {
            this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
                lineNumbers: true,
                mode: 'application/json',
                gutters: ['CodeMirror-lint-markers'],
                theme: 'rubyblue',
                lint: true,

            })
            // 将json文件格式化显示
           // this.jsonEditor.setValue(JSON.stringify(JSON.parse(this.value), null, 2))
            // 当输入框内容发生变化 更新value值
            this.jsonEditor.on('change', cm => {
                this.handleInput(cm)
                this.$emit('changed', cm.getValue())
                this.$emit('input', cm.getValue())
            })
        },
        */
        methods: {
            getValue() {
                return this.jsonEditor.getValue()
            },
            handleInput(e) {
                if (this.changeFn) {
                    this.changeFn(e.getValue())
                }
            },
            //编辑hosts
            getIpArray() {
                //TODO: api get data from mysql or redis
                //alert(this.hostItems.selected)
                //console.log(this.hostItems.selected.toString().split(","))
                //return [1,4]
                this.ipAllLists = []  //数组对象
                this.ipLists = []    //索引
                //var ipArray = ["172.168.2.103","172.168.2.104","172.168.2.105","172.168.2.106","172.168.2.107","172.168.2.108","192.168.138.128"]
                //var selectedIp = this.hostItems.selected.toString().split(",")
                var selectedIp = this.presentIpList
                // console.log("select ip ..." ,selectedIp )
                // console.log("select ip ..." ,this.ipALL )
                //this.ipALL = ipArray   //所有清单赋值给变量
                for (let i = 0; i < this.ipALL.length; i++) {
                    this.ipAllLists.push({
                        key: i,
                        label: this.ipALL[i],
                    });
                }
                    for (let i = 0; i < selectedIp.length; i++) {
                        this.ipLists.push(this.ipALL.indexOf(selectedIp[i]));
                    }

            },
            newIpGroup() {
                //TODO: api get data from mysql or redis
                //alert(this.hostItems.selected)
                //console.log(this.hostItems.selected.toString().split(","))
                //return [1,4]
                this.ipAllLists = []  //数组对象
                this.ipLists = []    //索引
                //var ipArray = ["172.168.2.103","172.168.2.104","172.168.2.105","172.168.2.106","172.168.2.107","172.168.2.108"]

                //this.ipALL = ipArray   //所有清单赋值给变量
                for (let i = 0; i < this.ipALL.length; i++) {
                    this.ipAllLists.push({
                        key: i,
                        label: this.ipALL[i],
                    });
                }
            },
            cancelEdit() {
                this.ipLists = []
                this.visible2 = false
            },
            confirmEdit() {
                //alert(this.ipLists)
                //return

                var tmp = []
                for (let i = 0; i < this.ipLists.length; i++) {
                    tmp.push(this.ipALL[this.ipLists[i]])
                }
                //TODO: (api) set vaule to mysql or redis
                this.presentIpList = tmp
                // console.log("api to posts")
                // console.log(this.presentIpList.join(","))
                // console.log(this.hostItems.selected)
                var param = {name:this.hostItems.selected,iplist:this.presentIpList.join(",")}
                updateItemHosts(param)

                this.ipLists = []
                this.visible2 = false
            },
            cancelEdit2() {
                this.ipLists = []
                this.visible3 = false
            },
            confirmAdd() {
                //alert(this.ipLists)
                var tmp = []
                for (let i = 0; i < this.ipLists.length; i++) {
                    tmp.push(this.ipALL[this.ipLists[i]])
                }
                //TODO: (api) set vaule to mysql or redis
                //TODO: (api) set itgroup(name,hots) to mysql or redis
                this.newIpGroupItem.newIpList = tmp
                let param = {name:this.newIpGroupItem.name,iplist:this.newIpGroupItem.newIpList.join(",")}
                AddItemHosts(param).then((res) => {
                    // console.log(res.code)
                    if (res.code === 400) {
                        alert(res.message)
                    }
                })
                this.ipLists = []
                this.visible3 = false
            },
            yamlSyntaxCheck(){
                //yamlParse.parse(test,"")
                try {
                    //console.log("test here",$(".CodeMirror-code").text())
                    //var cm = $(".CodeMirror")[0].CodeMirror;
                    var cm = $(".yamlcode  .CodeMirror")[0].CodeMirror;  //怕多个codemirror引起的混乱
                    var doc = cm.getDoc();
                    // console.log(doc.getValue().toString())
                    if (doc.getValue().toString().trim() == 0) {
                        this.yamlSyntaxErrorMsgOrExecOutput = "输入不准为空"
                        return
                    }
                    var obj = jsyaml.load(doc.getValue().toString());
                    //var obj = jsyaml.load('greeting: hello\n name: world');
                    //var obj = jsyaml.load(doc.getValue().toString());
                    //console.log("the result is",obj)
                    this.yamlSyntaxErrorMsgOrExecOutput = doc.getValue().toString()
                    this.buttonClickExec = false
                } catch (error) {
                    // console.log("the error is",error.message)

                    this.yamlSyntaxErrorMsgOrExecOutput = error.message
                    this.buttonClickExec = true
                }
            },
            doAnsibleJob() {

                if (this.hostItems.selected === "") {
                    this.yamlSyntaxErrorMsgOrExecOutput = "请选择主机组"
                    return
                }

                let self = this
                // alert("TODO: ansible-play this yaml job\n TODO:后台检测任务语法")
                // console.log(self.presentIpList.join(","))
                var cm = $(".yamlcode  .CodeMirror")[0].CodeMirror;  //怕多个codemirror引起的混乱
                var doc = cm.getDoc();
                // console.log(doc.getValue().toString())
                let param = {ipLine:self.presentIpList.join(",") , content: doc.getValue().toString() }
                self.ansiblePlaybookOutPutLoading = true
                //ansible-playbook yaml
                runAnsiblePlaybook(param).then((res) => {
                    // console.log(res)
                    self.yamlSyntaxErrorMsgOrExecOutput = res.result
                    self.ansiblePlaybookOutPutLoading = false
                })


            },
            //ansible
            chooseHosts(){
                getHostList().then((res) => {
                        // console.log(res.data.hosts)
                    this.hostItems.options = res.data.hosts
                    }
                )
            },
            changeItem() {
                let self = this

                self.moduleform.describe = ""
                this.buttonClick=false
                this.getSelectedIpList()

            },
            changeUsage(){
                let self = this


                switch (self.moduleform.name) {
                    case "ping":
                        self.moduleform.ansibleUsage = "";

                        break;
                    case "shell":
                        self.moduleform.ansibleUsage = "echo helloWorld";

                        break;
                    case "copy":
                        self.moduleform.ansibleUsage = "src=/etc/fstab dest=/opt/fstab.bk owner=root mode=644";

                        break;
                    case "yum":
                        self.moduleform.ansibleUsage = "name = mysql";

                        break;
                    case "cron":
                        self.moduleform.ansibleUsage = 'minute="*/1" job="/usr/bin/echo heihei >> /opt/test.txt" name="test cron"';

                        break;
                    case "file":
                        self.moduleform.ansibleUsage = 'path=/opt/file.txt owner=test02 group=mysql mode=666';

                        break;
                    case "script":
                        self.moduleform.ansibleUsage = "/data/shell/script.sh";

                        break;
                    case "user":
                        self.moduleform.ansibleUsage = "name = devops";

                        break;


                }
                self.moduleform.commandLine = 'ansible ' + self.hostItems.selected + ' -m ' +  self.moduleform.name + " " + "'" + self.moduleform.ansibleUsage + "'"
            },
            runAnsibleCmdByModule(formName){



                this.$refs[formName].validate((valid) => {
                    if (valid) {
                        if (this.hostItems.selected === "") {
                            this.ansibleModuleResult = "请选择主机组"
                            return
                        }


                        let self = this
                        self.ansibleModuleOutPutLoading = true
                        // console.log(self.moduleform.commandLine)
                        // console.log(self.presentIpList.join(","))
                        let param = {name:self.moduleform.name, param: self.moduleform.describe,ipLine:self.presentIpList.join(",") }

                        runAnsibleModuleCmd(param).then((res) => {
                            // console.log(res)
                            self.ansibleModuleResult = res.result
                            self.ansibleModuleOutPutLoading = false
                        })
                    } else {
                        // console.log('error submit!!');
                        return false;
                    }
                });





            },

            getSelectedIpList( ) {
                this.hostItems.options.forEach(v=> {
                    if (v.name === this.hostItems.selected) {
                        // console.log("the finanellllll " , v.iplist.toString().split(','))
                        this.presentIpList = v.iplist.toString().split(',')

                    }
                    }
                )
            },
            getAllIpLists(){
                getIpLists().then((res) => {
                        this.ipALL = res.data.iplists
                    }
                )
            },
            getAllTemplate(){
                getTemplateLists().then((res) => {
                        //this.ipALL = res.data.iplists
                        // console.log(res.data.path)
                    this.playbookOptions[0].options = res.data.path
                    }
                )
            },

            loadYaml() { //远程加载模板文件
                this.buttonClickExec = true
                var cm = $(".yamlcode  .CodeMirror")[0].CodeMirror;  //怕多个codemirror引起的混乱
                var doc = cm.getDoc();
                doc.setValue("")
                // console.log(this.playbookValue.substring(1,9))
                if (this.playbookValue.substring(1,9) === "template") {
                    let paramUrl =  this.playbookValue
                    //LoadTemplateFile(paramUrl)
                    LoadTemplateFile(paramUrl).then((res) => {
                            // console.log(res)
                            doc.setValue(res)
                        }
                    )

                }

            },
            handleAvatarSuccess(res, file) {
                //console.log(res.filename)
                //console.log(file)
                this.$message({
                    message: res.filename + " 上传成功" ,
                    type: 'success'
                });
            },
            handleAvatarError(res) {
                this.$message({
                    message: "上传失败" + res.message ,
                    type: 'success'
                });

            },
            beforeAvatarUpload(file) {
                const isLt500K = file.size / 1024  < 500;
                if (!isLt500K) {
                    this.$message.error('上传文件大小不能超过 500Kb!');
                }
                return isLt500K
            }

        },
        components: {
            editYaml,
        },
        mounted() {

            this.getAllIpLists();
            this.getAllTemplate();
        },
        computed: {
          getHostGroupName() {
              return this.hostItems.selected
          },
            getHostGroupParam() {
                return this.moduleform.describe
            }
        },
        watch: {
            getHostGroupName(val) {
                let self = this
                self.moduleform.commandLine = 'ansible ' + val + ' -m ' +  self.moduleform.name + " " + "'" + self.moduleform.ansibleUsage + "'"
            },
            getHostGroupParam(val) {
                let self = this
                self.moduleform.commandLine = 'ansible ' + self.hostItems.selected + ' -m ' +  self.moduleform.name + " " + "'" + val + "'"
            }

        },

    }
</script>

<style>


    #ansible-manager .json-editor .cm-s-rubyblue span.cm-string {
        color: #F08047;
    }
    #ansible-manager .hosts-select {
        margin-top:5px;
        margin-bottom:5px;
    }

    #ansible-manager  .title-toor {
        font-size: 120%;
        margin-top:5px;
        margin-bottom:5px;
    }
    #ansible-manager  .add-group-input {
        width: 100px;
        margin-top:5px;
        margin-bottom:5px;
    }


    #ansible-manager .bg-card {
        background-color: #FAFAFA;
    }

    #ansible-manager .el-textarea__inner {
        background-color: #fdf6e3;
    }
    #ansible-manager .el-card__body {
        padding: 5px 20px 20px 20px;
    }
</style>

